(function($, loc, doc){    
    /**
     * Creates an URLParser instance
     *
     * @classDescription    Creates an URLParser instance
     * @return {Object}    return an URLParser object
     * @param {String} url    The url to parse
     * @constructor
     * @exception {String}  Throws an exception if the specified url is invalid
     */
    var _URLParser = function URLParser(url) {    
        this._urlFields = {
            'Username' : 4,
            'Password' : 5,
            'Port' : 7,
            'Protocol' : 2,
            'Host' : 6,
            'Pathname' : 8,
            'URL' : 0,
            'Querystring' : 9,
            'Fragment' : 10
        };
        this._urlFieldValues = {};
        
        this.urlRegex = /^((\w+):\/\/)?((\w+):?(\w+)?@)?([^\/\?:]+):?(\d+)?(\/?[^\?#]+)?\??([^#]+)?#?(\w*)/;
    
        for (var urlField in this._urlFields) {
            this['get' + urlField] = (function(urlField) {
                return function() {
                    return this._urlFieldValues[urlField];
                };
            } )(urlField);
        }
    
        if ( typeof url != 'undefined') {
            this.setURL(url);
        }
    };    
    /**
     * @method
     * @param {String} url    The url to parse
     * @exception {String}     Throws an exception if the specified url is invalid
     */
    _URLParser.prototype.setURL = function(url) {
        var urlFieldsMatch = this.urlRegex.exec(url);
        if (!urlFieldsMatch)
            throw "DPURLParser::_parse -> Invalid URL";
    
        for (var urlField in this._urlFields) {
            this._urlFieldValues[urlField] = '';
            if ( typeof urlFieldsMatch[this._urlFields[urlField]] != 'undefined') {
                this._urlFieldValues[urlField] = urlFieldsMatch[this._urlFields[urlField]];
            }
        }
    };
   
    //---------------------------------------------------------------------------------------------------------------
    
    ujs.define('loc', 'ujs.browser', {
        URLParser : _URLParser,
        /**
         * 获取指定name的URL参数值 
         */
        getQuery : function(name){
            var result = loc.search.match(
                new RegExp("[\?\&]" + name + "=([^\&]+)","i")
            ); 
            return ( result && result.length > 1 ) ? result[1] : '';               
        },
        /**
         * get all query strings.
         * @url {String} : 需要解析的url地址，若不存在，则使用当前页面地址。
         * @return {JSON}.  
         */
        getQuerys : function(url){
            url = url ? url.replace(/(.*\?)/g,'').replace(/#.*/gi,'') : loc.search.substring(1);
            var allQuerys = url, 
                querys = {};
                
            if(allQuerys){
                var allQuerysArr = allQuerys.split("&");
                for (var i = 0, len = allQuerysArr.length; i < len; i++) {
                    var queryItem = allQuerysArr[i].split("=");
                    querys[ queryItem[0] ] = queryItem[1];
                }
            }
            return querys;
        },
        //append url query string.
        //if exists, replace it.
        addQuery : function(url, querysMap, isRedirect){        
            //处理 function( querysMap, isRedirect )的情况。
            if(typeof url === 'object'){
                isRedirect = querysMap;
                querysMap = url;
                url = loc.href;
            }        
            //提取hash
            var hashDivisionArr = url.split('#'),  
                urlHash = hashDivisionArr[1];        
            //计算新的url.
            url = hashDivisionArr[0];        
            $.each(querysMap, function(key, val){     
                //TODO此处正则缺少(?=[\?\&])的边界限定.    
                var queryItemReg = new RegExp('{0}=[^\#\&]*'.format(key));
                if(queryItemReg.test(url)){
                    url = url.replace( queryItemReg, "{0}={1}".format(key, encodeURIComponent(val)) ); 
                } else {            
                    url += ( url.indexOf('?') < 0 ?  '?' : '&' ) + key + '=' +  encodeURIComponent(val);    
                }
            });
            //追加先前的hash.
            if( urlHash ){
                url += '#' + urlHash;
            }        
            //重定向当前页面.
            if(isRedirect === true){
                loc.replace(url);
            }           
            return url;
        },
        /**
         * TODO,未实现 
         */
        ping : function(url, cb){
            var imgHelper = new Image();
            imgHelper.onload = function(){
                debugger
            }    
            imgHelper.onerror = function(){
                debugger
            }
            imgHelper.src = url;
        },        
        //获取当前url的segment array.
        //@return Array.
        getSegments : function() {
            var segments = loc.pathname.replace(/^\/|\/$/gi, '').split('/');        
            return segments[0] ? segments : null;
        },
        removeQuery : function(url, key){
            var argsCount = arguments.length;         
            if(!argsCount){
                return null;
            } else if(argsCount == 1){
                key = url;
                url = loc.href;
            }
            url = url.replace(new RegExp('&' + key + '=[^&#]*', 'gi'), '')
                .replace(new RegExp(key + '=[^&#]*&', 'gi'), '')
                .replace(new RegExp(key + '=[^&#]*#', 'gi'), '#')            
                .replace(/\?#/gi,'#')
                .replace(/\?$/gi,'')
                .replace(new RegExp('\\?' + key + '=[^&#]*$', 'gi'), '');
            return url;
        },
        /**
         * 清空当前页面的hash. 
         */
        clearHash : function(){
            loc.hash = '';
        },
        /**
         * 当前页面跳转到指定的hash. 
         */
        toHash : function(hashName){
            if( hashName ){
                loc.hash = hashName;
            }
        },
        /**
         * 跳转到登录页面. 
         * @param {Boolean} : [isTakenCBUrl], 默认为 true.
         * @param {Object} : [querys], url参数.
         */
        toLoginPage : function(isTakenCBUrl, querys){            
            //兼容toLoginPage(querys)
            if(Type.isObject(isTakenCBUrl)){
                querys = isTakenCBUrl;
                isTakenCBUrl = true;
            }          
            if(loc.href.indexOf('dev=1') > -1){    
                //若强制使用开发模式，则禁用跳转，以便于调试.    
                return false;    
            }
            //若非login存在退出提示，则退出前禁掉。
            window.onbeforeunload = null;
            //清除客户端 SessionID.
            sessionStorage.setItem( 'sid', null );
            //获取顶级的 window 对象.
            var currentLoc = loc;
            if(window.top !== window){
                currentLoc = window.top.location;
            }
            if(!window.ujsConfig || !window.ujsConfig.loginPageUrl){
                throw '您未配置登录页地址,配置位置为:ujsConfig.loginPageUrl, 来自：location.toLoginPage。';
                return;
            }
            //计算登录页地址.
            var loginPageUrl = ujsConfig.loginPageUrl;
            if(Type.isFunction(loginPageUrl)){
                loginPageUrl = loginPageUrl.call(ujsConfig);
            }
            if(isTakenCBUrl !== false){
                loginPageUrl += '?url={0}'.format( encodeURIComponent( currentLoc.href.replace(currentLoc.origin,'') ) );
            }    
            if(Type.isObject(querys)){
                loginPageUrl = ujs.browser.loc.addQuery(loginPageUrl, querys);
            } 
            currentLoc.href = loginPageUrl;
        },
        /**
         * 跳转到系统首页，若登录页存在回调地址，则优先跳转到回调地址. 
         */
        toIndexPage : function(){
            if(loc.href.indexOf('dev=1') > -1){  
                //若强制使用开发模式，则禁用跳转，以便于调试.      
                return false;    
            }       
            var backUrl = this.getQuery('url');
            var indexPageUrl = '/';  //默认首页地址为'/'.      
            if(window.ujsConfig && window.ujsConfig.indexPageUrl){
                indexPageUrl = window.ujsConfig.indexPageUrl;
            }
            loc.replace( backUrl ? decodeURIComponent(backUrl) : indexPageUrl );
        },
        /**
         * 获取url中指定的文档搜索词.
         * 文档搜索词在hash中指定，并可以指定多个搜索词，如下hash中的search部分：
         * #toolbar=1&navpanes=1&search="name json"
         * 
         * @param {Function} hasKeyHandler : search key存在时执行的回调函数。
         * @param {Function} noKeyHandler : 未提取到search key时的回调函数。
         */    
        getSearchKeys : function(hasKeyHandler, noKeyHandler){
            var searchKeysStr = loc.hash.match(new RegExp('[\#\&]search=\"([^\&]+)\"', "i"));            
            if (searchKeysStr && searchKeysStr[1]) {        
                var searchKeys = decodeURIComponent( searchKeysStr[1] ); 
                if(hasKeyHandler){
                    hasKeyHandler(searchKeys);
                }
                return searchKeys;
            } else {
                if(noKeyHandler){
                    noKeyHandler();
                }
                return null;         
            }
        },
        //添加到收藏夹
        addToBookmark : function(url){
            var title = doc.title;
            url = url || loc.href;
            if (doc.all) {
                window.external.AddFavorite(url, title);
            } else if (window.sidebar) {
                window.sidebar.addPanel(title, url, "");
            } else {
                alert("您的浏览器不支持加入收藏夹功能,请使用 Ctrl+D 添加!");
            }
        },
        //将当前地址设置为浏览器首页.
        setAsHomepage : function(url) {
            url = url || loc.href;
            if (doc.all) {
                doc.body.style.behavior = 'url(#default#homepage)';
                doc.body.setHomePage(url);
            } else if (window.sidebar) {
                if (window.netscape) {
                    try {
                        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
                    } catch(e) {
                        alert("该操作被浏览器拒绝，如果想启用该功能，请在地址栏内输入about:config, 然后将项 signed.applets.codebase_principal_support 值该为true");
                    }
                }
                var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
                prefs.setCharPref('browser.startup.homepage', url);
            }
        }
    });
    
    //将所有的url参数缓存到location对象中.
    ujs.browser.loc.querys = ujs.browser.loc.getQuerys();     
    
})($, window.location, document);